home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dcc / place.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  11KB  |  523 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  PLACE.C
  9.  *
  10.  *  PlaceRexxCommand()
  11.  *
  12.  *  Send an AREXX command according to arguments and RexxHostName
  13.  */
  14.  
  15. #ifdef AMIGA
  16.  
  17. #include "rexx.h"
  18.  
  19. void ClearDiceRexxPort(MsgPort *);
  20. void RexxReply(void *, long, char *);
  21.  
  22. static MsgPort RexxPort;            /*    master port    */
  23. static char    *RexxPortName = "REXX";      /*  master port name    */
  24.  
  25. static short    GlobalFlag;
  26. static short    MasterPortValid;
  27.  
  28. static List    RexxWIPList;
  29. static List    RexxRIPList;
  30. static List    RexxAuxPortList;
  31. static short    RexxPortInitialized;
  32.  
  33. short    RexxSigBit;    /*  master signal   */
  34.  
  35. __autoinit
  36. static void
  37. __dice_rexx_init()
  38. {
  39.     /*
  40.      *    initialize the list that tracks rexx requests sent
  41.      */
  42.  
  43.     RexxWIPList.lh_Head = (Node *)&RexxWIPList.lh_Tail;
  44.     RexxWIPList.lh_TailPred = (Node *)&RexxWIPList.lh_Head;
  45.  
  46.     /*
  47.      *    initialize the list that tracks rexx requests received
  48.      */
  49.  
  50.     RexxRIPList.lh_Head = (Node *)&RexxRIPList.lh_Tail;
  51.     RexxRIPList.lh_TailPred = (Node *)&RexxRIPList.lh_Head;
  52.  
  53.     /*
  54.      *    initialize the auxillary port list and add our master node to
  55.      *    it.
  56.      */
  57.  
  58.     RexxAuxPortList.lh_Head = (Node *)&RexxAuxPortList.lh_Tail;
  59.     RexxAuxPortList.lh_TailPred = (Node *)&RexxAuxPortList.lh_Head;
  60.  
  61.     /*
  62.      *    Get our master signal and create master port
  63.      */
  64.  
  65.     RexxSigBit = AllocSignal(-1);
  66.  
  67.     if (RexxHostName)
  68.     CreateDiceRexxPort(NULL, RexxHostName);
  69.  
  70.     RexxPortInitialized = 1;
  71. }
  72.  
  73. /*
  74.  *  The exit code can be called at any point... there might be multiple
  75.  *  messages queued, in the queue, or in processing.  We must do the
  76.  *  following items in order:
  77.  *
  78.  *    (1) prevent any further messages from being received
  79.  *    (2) return any messages queued-in or in processing
  80.  *    (3) wait for any outgoing messages to be returned
  81.  */
  82.  
  83. __autoexit
  84. static void
  85. __dice_rexx_exit()
  86. {
  87.     if (RexxPortInitialized) {
  88.     RexxPortNode *rp;
  89.  
  90.     /*
  91.      *  prevent further messages from being received
  92.      */
  93.  
  94.     for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head;
  95.          rp->rp_Node.ln_Succ; rp = (RexxPortNode *)rp->rp_Node.ln_Succ) {
  96.         if (rp->rp_IsPublic) {
  97.         RemPort(rp->rp_MsgPort);
  98.         rp->rp_IsPublic = 0;
  99.         }
  100.     }
  101.  
  102.     /*
  103.      *  return any messages in processing or queued-in
  104.      */
  105.  
  106.     for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head;
  107.          rp->rp_Node.ln_Succ; rp = (RexxPortNode *)rp->rp_Node.ln_Succ)
  108.         ClearDiceRexxPort(rp->rp_MsgPort);
  109.  
  110.     /*
  111.      *  wait for replies from rexx commands we have sent.  Since we
  112.      *  have cleared all other messages, no lockout conditions can
  113.      *  occur at this point.
  114.      */
  115.  
  116.     {
  117.         RexxIPNode *rip;
  118.  
  119.         while (rip = (RexxIPNode *)RemHead(&RexxWIPList)) {
  120.         if (rip->rip_Returned == 0) {
  121.             while (((Message *)rip->rip_RexxMsg)->mn_Node.ln_Type != NT_REPLYMSG)
  122.             Wait(1 << RexxSigBit);
  123.             Forbid();
  124.             Remove(&rip->rip_RexxMsg->rm_Node.mn_Node);
  125.             Permit();
  126.             rip->rip_Returned = 1;
  127.         }
  128.         ClearRexxMsg(rip->rip_RexxMsg, 1);
  129.         DeleteRexxMsg(rip->rip_RexxMsg);
  130.         }
  131.     }
  132.  
  133.     /*
  134.      *  Delete the ports.  Since we have cleared rp_IsPublic it will
  135.      *  not try to RemPort() them again.
  136.      */
  137.  
  138.     while ((rp = (RexxPortNode *)RexxAuxPortList.lh_Head) != (RexxPortNode *)&RexxAuxPortList.lh_Tail)
  139.         DeleteDiceRexxPort(rp->rp_MsgPort);
  140.  
  141.     /*
  142.      *  Free our master signal
  143.      */
  144.  
  145.     FreeSignal(RexxSigBit);
  146.     RexxPortInitialized = 0;
  147.     }
  148. }
  149.  
  150. long
  151. PlaceRexxCommandDirect(port, remoteName, arg, pres, pec)
  152. MsgPort *port;
  153. char *remoteName;
  154. char *arg;
  155. char **pres;
  156. long *pec;
  157. {
  158.     char *rpn = RexxPortName;
  159.     long r;
  160.  
  161.     RexxPortName = remoteName;
  162.     r = PlaceRexxCommand(port, arg, pres, pec);
  163.     RexxPortName = rpn;
  164.     return(r);
  165. }
  166.  
  167. long
  168. PlaceRexxCommand(port, arg, pres, pec)
  169. MsgPort *port;
  170. char *arg;
  171. char **pres;
  172. long *pec;
  173. {
  174.     RexxIPNode rip;
  175.     long rc = -2;
  176.  
  177.     if (port == NULL) {
  178.     if (MasterPortValid == 0)
  179.         return(-1);
  180.     port = &RexxPort;
  181.     }
  182.  
  183.     if (pres)
  184.     *pres = NULL;
  185.     if (pec)
  186.     *pec = 0;
  187.  
  188.  
  189.     if (RexxSysBase) {
  190.     rc = -1;
  191.  
  192.     if (rip.rip_RexxMsg = CreateRexxMsg(port, ((RexxHostName) ? RexxHostName : "UNKNOWN"), port->mp_Node.ln_Name)) {
  193.         MsgPort *arexxPort;
  194.  
  195.         rip.rip_RexxMsg->rm_Node.mn_Node.ln_Name = "REXX";
  196.         rip.rip_RexxMsg->rm_Action = RXCOMM;
  197.         ARG0(rip.rip_RexxMsg) = CreateArgstring(arg,strlen(arg));
  198.  
  199.         AddHead(&RexxWIPList, &rip.rip_Node);
  200.         rip.rip_Returned = 0;
  201.         rip.rip_RexxPort = port;
  202.  
  203.         Forbid();
  204.         if (arexxPort = (MsgPort *)FindPort(RexxPortName)) {
  205.         PutMsg(arexxPort, (Message *)rip.rip_RexxMsg);
  206.         Permit();
  207.  
  208.         while (rip.rip_Returned == 0) {
  209.             RexxPortNode *rp;
  210.  
  211.             /*
  212.              *    Since this is the only wait on this signal there
  213.              *    can be no lockout condition.
  214.              */
  215.  
  216.             Wait(1 << RexxSigBit);
  217.             for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head;
  218.                  rp->rp_Node.ln_Succ; rp = (RexxPortNode *)(rp->rp_Node.ln_Succ))
  219.             ProcessRexxCommands(rp->rp_MsgPort);
  220.         }
  221.         } else {
  222.         Permit();
  223.         }
  224.         Remove(&rip.rip_Node);
  225.  
  226.         /*
  227.          *    Process result / return code here if rip.rip_Returned == 0
  228.          *    then we were not able to dispatch the message
  229.          */
  230.  
  231.         if (rip.rip_Returned) {
  232.         if ((rc = rip.rip_RexxMsg->rm_Result1) == 0) {
  233.             if (pres && rip.rip_RexxMsg->rm_Result2)
  234.             *pres = strdup((char *)rip.rip_RexxMsg->rm_Result2);
  235.         } else {
  236.             if (pec)
  237.             *pec = (long)rip.rip_RexxMsg->rm_Result2;
  238.         }
  239.         }
  240.         ClearRexxMsg(rip.rip_RexxMsg, 1);
  241.         DeleteRexxMsg(rip.rip_RexxMsg);
  242.     }
  243.     }
  244.     return(rc);
  245. }
  246.  
  247. void
  248. ProcessRexxCommands(port)
  249. MsgPort *port;
  250. {
  251.     RexxMsg *msg;
  252.  
  253.     if (port == NULL) {
  254.     RexxPortNode *rp;
  255.  
  256.     for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head;
  257.          rp->rp_Node.ln_Succ; rp = (RexxPortNode *)(rp->rp_Node.ln_Succ))
  258.         ProcessRexxCommands(rp->rp_MsgPort);
  259.     return;
  260.     }
  261.  
  262.     while (msg = (RexxMsg *)GetMsg(port)) {
  263.     if ((msg->rm_Node.mn_Node.ln_Type == NT_MESSAGE) && IsRexxMsg(msg)) {
  264.         RexxIPNode rip;
  265.         char *str = NULL;
  266.         long rc;
  267.  
  268.         rip.rip_RexxMsg = msg;
  269.         rip.rip_RexxPort = port;
  270.         AddTail(&RexxRIPList, &rip.rip_Node);
  271.         rc = DoRexxCommand(msg, port, ARG0(msg), &str);
  272.         Remove(&rip.rip_Node);
  273.         RexxReply(msg, rc, str);
  274.     } else {
  275.         RexxIPNode *rip;
  276.  
  277.         for (rip = (RexxIPNode *)RexxWIPList.lh_Head; rip->rip_Node.ln_Succ; rip = (RexxIPNode *)rip->rip_Node.ln_Succ) {
  278.         if (msg == rip->rip_RexxMsg) {
  279.             rip->rip_Returned = 1;
  280.             break;
  281.         }
  282.         }
  283.     }
  284.     }
  285. }
  286.  
  287. /*
  288.  *  Create a global DICE rexx port
  289.  */
  290.  
  291. short
  292. CreateGlobalDiceRexxPort(port, name)
  293. MsgPort *port;
  294. char *name;
  295. {
  296.     short r;
  297.  
  298.     GlobalFlag = 1;
  299.     r = CreateDiceRexxPort(port, name);
  300.     GlobalFlag = 0;
  301.  
  302.     return(r);
  303. }
  304.  
  305. /*
  306.  *  Create an application DICE rexx port
  307.  */
  308.  
  309. short
  310. CreateDiceRexxPort(port, name)
  311. MsgPort *port;
  312. char *name;
  313. {
  314.     RexxPortNode *rp;
  315.     short pno;
  316.     short isPublic;
  317.     short allocSize;
  318.  
  319.     if (port == NULL) {
  320.     port = &RexxPort;
  321.     MasterPortValid = 1;
  322.     }
  323.  
  324.     if (name == NULL) {
  325.     name = "PRIVATE-REXX-PORT";
  326.     isPublic = 0;
  327.     } else {
  328.     isPublic = 1;
  329.     }
  330.     allocSize = sizeof(RexxPortNode) + strlen(name) + 4;
  331.  
  332.     rp = AllocMem(allocSize, MEMF_PUBLIC|MEMF_CLEAR);
  333.  
  334.     rp->rp_Node.ln_Type = allocSize;
  335.     rp->rp_MsgPort = port;
  336.     rp->rp_IsPublic = isPublic;
  337.     AddTail(&RexxAuxPortList, &rp->rp_Node);
  338.  
  339.     port->mp_Node.ln_Name = (char *)(rp + 1);
  340.  
  341.     port->mp_Node.ln_Type = NT_MSGPORT;
  342.     port->mp_Node.ln_Pri = 1;
  343.     port->mp_Flags = PA_SIGNAL;
  344.     port->mp_SigBit = RexxSigBit;
  345.     port->mp_SigTask = FindTask(NULL);
  346.     port->mp_MsgList.lh_Head = (Node *)&port->mp_MsgList.lh_Tail;
  347.     port->mp_MsgList.lh_TailPred = (Node *)&port->mp_MsgList.lh_Head;
  348.  
  349.     /*
  350.      *    Give the port a real name according to AREXX semantics,
  351.      *    portname.NN (01-99)
  352.      */
  353.  
  354.     Forbid();
  355.  
  356.     if (GlobalFlag || isPublic == 0) {
  357.     strcpy(port->mp_Node.ln_Name, name);
  358.     if (isPublic && FindPort(port->mp_Node.ln_Name))
  359.         pno = -1;
  360.     else
  361.         pno = 0;
  362.     } else {
  363.     for (pno = 1; pno < 100; ++pno) {
  364.         sprintf(port->mp_Node.ln_Name, "%s.%02d", name, pno);
  365.         if (FindPort(port->mp_Node.ln_Name) == NULL)
  366.         break;
  367.     }
  368.     if (pno == 100)
  369.         pno = -1;
  370.     }
  371.  
  372.     if (isPublic)
  373.     AddPort(port);
  374.  
  375.     if (pno < 0)
  376.     DeleteDiceRexxPort(port);
  377.     else if (port == (MsgPort *)&RexxPort && RexxHostName == NULL)
  378.     RexxHostName = port->mp_Node.ln_Name;
  379.  
  380.     Permit();
  381.  
  382.     return(pno);
  383. }
  384.  
  385. /*
  386.  *  Delete a DICE rexx port.  Note that there can be no outgoing messages
  387.  *  in-progress for this port for this command to work properly.
  388.  */
  389.  
  390. void
  391. DeleteDiceRexxPort(port)
  392. MsgPort *port;
  393. {
  394.     /*
  395.      *    check if valid port, remove RexxPortNode if found
  396.      */
  397.  
  398.     {
  399.     RexxPortNode *rp;
  400.  
  401.     for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head;
  402.          rp->rp_Node.ln_Succ; rp = (RexxPortNode *)rp->rp_Node.ln_Succ) {
  403.         if (rp->rp_MsgPort == port) {
  404.         Remove(&rp->rp_Node);
  405.         if (rp->rp_IsPublic)
  406.             RemPort(port);
  407.         FreeMem(rp, rp->rp_Node.ln_Type);
  408.         break;
  409.         }
  410.     }
  411.     if (rp == NULL)
  412.         return;
  413.     }
  414.  
  415.     ClearDiceRexxPort(port);
  416.  
  417.     /*
  418.      *    clear port info
  419.      */
  420.  
  421.     clrmem(port, sizeof(MsgPort));
  422.  
  423.     if (port == (MsgPort *)&RexxPort)
  424.     MasterPortValid = 0;
  425. }
  426.  
  427. void
  428. ClearDiceRexxPort(port)
  429. MsgPort *port;
  430. {
  431.     /*
  432.      *    kill any received messages that are in progress
  433.      */
  434.  
  435.     {
  436.     RexxIPNode *rip;
  437.     RexxIPNode *rip_next;
  438.  
  439.     for (rip = (RexxIPNode *)RexxRIPList.lh_Head; rip->rip_Node.ln_Succ; rip = rip_next) {
  440.         rip_next = (RexxIPNode *)rip->rip_Node.ln_Succ;
  441.         if (rip->rip_RexxPort == port) {
  442.         Remove(&rip->rip_Node);
  443.         RexxReply(rip->rip_RexxMsg, 30, NULL);
  444.         }
  445.     }
  446.     }
  447.  
  448.  
  449.     /*
  450.      *    clear out any messages pending on the port
  451.      */
  452.  
  453.     {
  454.     RexxMsg *msg;
  455.  
  456.     while (msg = (RexxMsg *)GetMsg(port)) {
  457.         if ((msg->rm_Node.mn_Node.ln_Type == NT_MESSAGE) && IsRexxMsg(msg)) {
  458.         RexxReply(msg, 30, NULL);
  459.         } else {
  460.         RexxIPNode *rip;
  461.  
  462.         for (rip = (RexxIPNode *)RexxWIPList.lh_Head;
  463.              rip->rip_Node.ln_Succ; rip = (RexxIPNode *)rip->rip_Node.ln_Succ) {
  464.             if (msg == rip->rip_RexxMsg) {
  465.             rip->rip_Returned = 1;
  466.             break;
  467.             }
  468.         }
  469.         }
  470.     }
  471.     }
  472. }
  473.  
  474. void
  475. RexxReply(vmsg, res1, str)
  476. void *vmsg;
  477. long res1;
  478. char *str;
  479. {
  480.     RexxMsg *msg = vmsg;
  481.  
  482.     if (msg->rm_Result1 = res1) {
  483.     msg->rm_Result2 = 0;
  484.     } else {
  485.     if (str)
  486.         msg->rm_Result2 = (long)CreateArgstring(str, strlen(str));
  487.     else
  488.         msg->rm_Result2 = 0;
  489.     }
  490.     ReplyMsg((Message *)msg);
  491. }
  492.  
  493. /*
  494.  *  Obtain the fully qualified name of an application port (name.xx) and
  495.  *  return an integer.    Returns -1 if the port does not contain a .xx
  496.  *  extension.
  497.  */
  498.  
  499. int
  500. GetDiceRexxPortSlot(port, pname)
  501. MsgPort *port;
  502. char **pname;
  503. {
  504.     int slotNo = -1;
  505.     char *ptr;
  506.  
  507.     if (port == NULL)
  508.     port = &RexxPort;
  509.     if (ptr = strrchr(port->mp_Node.ln_Name, '.')) {
  510.     char *tmp;
  511.  
  512.     slotNo = strtol(ptr + 1, &tmp, 10);  /* must be base 10 re: '.01'... */
  513.     if (tmp == ptr)
  514.         slotNo = -1;
  515.     }
  516.     if (pname)
  517.     *pname = port->mp_Node.ln_Name;
  518.     return(slotNo);
  519. }
  520.  
  521. #endif
  522.  
  523.